from typing import List, Dict, Optional
from app.models.question import Question, QuestionSource, QuestionType, DifficultyLevel, QuestionStatus, QuestionOption
from app.models.chapter import Chapter
from app.services.llm_service import LLMService
import logging

logger = logging.getLogger(__name__)

class QuestionGenerator:
    def __init__(self):
        self.llm_service = LLMService()
    
    async def generate_questions_for_chapter(
        self,
        chapter_id: int,
        question_types: List[str] = [
            QuestionType.SINGLE_CHOICE,    # 单选题
            QuestionType.MULTIPLE_CHOICE,  # 多选题
            QuestionType.TRUE_FALSE,       # 判断题
            QuestionType.FILL_BLANK,       # 填空题
            QuestionType.SHORT_ANSWER,     # 简答题
        ],
        difficulty: str = DifficultyLevel.MEDIUM,
        num_questions: int = 5
    ) -> List[Dict]:
        """为指定章节生成题目"""
        try:
            # 获取章节内容
            chapter = await Chapter.get(id=chapter_id).prefetch_related('content')
            if not chapter or not chapter.content:
                raise ValueError(f"Chapter {chapter_id} or its content not found")
            
            text = chapter.content.processed_content or chapter.content.content
            saved_questions = []
            
            # 为每种题型分别生成题目
            for question_type in question_types:
                logger.info(f"Generating {question_type} questions for chapter {chapter_id}")
                try:
                    # 使用LLMService生成特定类型的题目
                    questions_data = await self.llm_service.generate_questions_from_text(
                        text=text,
                        question_types=[question_type],  # 每次只传入一种题型
                        difficulty=difficulty,
                        num_questions=num_questions
                    )
                    
                    # 保存生成的题目
                    for q_data in questions_data["questions"]:
                        # 创建题目记录
                        question = await Question.create(
                            title=q_data["title"],
                            content=q_data["content"],
                            type=question_type,  # 使用循环中的题型
                            difficulty=difficulty,
                            answer=q_data["answer"],
                            analysis=q_data["analysis"],
                            reference=q_data["reference"],
                            chapter=chapter,
                            status=QuestionStatus.DRAFT,  # 设置为草稿状态
                            # 根据题型设置特定字段
                            blank_count=q_data.get("blank_count") if question_type == QuestionType.FILL_BLANK else None,
                            standard_answer=q_data.get("standard_answer") if question_type == QuestionType.SHORT_ANSWER else None,
                            answer_points=q_data.get("answer_points") if question_type == QuestionType.SHORT_ANSWER else None
                        )
                        
                        # 如果是选择题，创建选项
                        if question_type in [QuestionType.SINGLE_CHOICE, QuestionType.MULTIPLE_CHOICE] and q_data.get("options"):
                            for idx, opt in enumerate(q_data["options"]):
                                await QuestionOption.create(
                                    question=question,
                                    option_label=opt["label"],
                                    content=opt["content"],
                                    is_correct=opt["is_correct"],
                                    order=idx
                                )
                        
                        # 创建题目来源记录
                        await QuestionSource.create(
                            question=question,
                            chapter_content=chapter.content,
                            content=q_data["reference"],
                            position={
                                "start": q_data["source_position"]["start"],
                                "end": q_data["source_position"]["end"]
                            }
                        )
                        
                        saved_questions.append(question)
                
                except Exception as e:
                    logger.error(f"Error generating {question_type} questions: {str(e)}")
                    # 继续处理下一个题型，而不是完全中断
                    continue
            
            if not saved_questions:
                raise ValueError("Failed to generate any questions")
                
            return saved_questions
            
        except Exception as e:
            logger.error(f"Error generating questions for chapter {chapter_id}: {str(e)}")
            raise
    
    async def generate_questions_batch(
        self,
        chapter_ids: List[int],
        question_types: List[str] = ["选择题", "判断题", "简答题"],
        difficulty: str = "中等",
        num_questions_per_chapter: int = 5,
        max_concurrent: int = 3
    ) -> Dict[int, List[Dict]]:
        """批量为多个章节生成题目"""
        import asyncio
        
        # 创建信号量控制并发
        semaphore = asyncio.Semaphore(max_concurrent)
        
        async def process_single_chapter(chapter_id: int) -> tuple:
            async with semaphore:
                try:
                    questions = await self.generate_questions_for_chapter(
                        chapter_id=chapter_id,
                        question_types=question_types,
                        difficulty=difficulty,
                        num_questions=num_questions_per_chapter
                    )
                    return chapter_id, questions
                except Exception as e:
                    logger.error(f"Error processing chapter {chapter_id}: {str(e)}")
                    return chapter_id, {"error": str(e)}
        
        # 并发处理所有章节
        tasks = [process_single_chapter(chapter_id) for chapter_id in chapter_ids]
        results = await asyncio.gather(*tasks)
        
        # 整理结果
        return {chapter_id: questions for chapter_id, questions in results if questions} 